import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class ViewProxy implements ModelListener {
	BufferedWriter out;
	Socket connection;
	ViewListener viewListener;
	ReaderThread rt;
	boolean active = false;
	/**
	 * Constructs the view proxy on the socket
	 * @param s Socket to use
	 */
	public ViewProxy(Socket s) {
		connection = s;
		try {
			out = new BufferedWriter(
					new OutputStreamWriter(s.getOutputStream()));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		rt = new ReaderThread(this);
		active = true;
		rt.start();

	}
	/**
	 * Sets thread to null, kinda pointless; it was created for no use
	 */
	public void trash() {
		rt = null;
	}
	/**
	 * Processes the message received from the reading thread of the socket
	 * @param command The string of the command
	 */
	public void processMsg(String command) {

		// TODO Auto-generated method stub
		String[] msgSplit = command.split(" ");
		if (msgSplit.length == 2) {
			if (msgSplit[0].equals("j")) {
				viewListener.join(ViewProxy.this, msgSplit[1]);
			}
		} else if (msgSplit.length == 4) {
			if (msgSplit[0].equals("p")) {
				ColorType c = ColorType.NONE;
				if (msgSplit[3].equals(ColorType.BLACK.toString())) {
					c = ColorType.BLACK;
				} else if (msgSplit[3].equals(ColorType.WHITE.toString())) {
					c = ColorType.WHITE;
				}
				viewListener.placePiece(Integer.parseInt(msgSplit[1]),
						Integer.parseInt(msgSplit[2]), c);
			}
		}
	}
	@Override
	public void joinSuccessful(ColorType c) {
		// TODO Auto-generated method stub
		try {
			out.write("j " + c);
			out.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			trash();
			active = false;
			viewListener.disconnected();
		}
	}

	public ViewListener getViewListener() {
		return viewListener;
	}

	public void setViewListener(ViewListener viewListener) {
		this.viewListener = viewListener;
	}

	@Override
	public void joinFailed() {
		// TODO Auto-generated method stub
		try {
			out.write("f");
			out.flush();
			viewListener = null;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void placePiece(int x, int y, ColorType c) {
		// TODO Auto-generated method stub
		try {
			out.write("p " + x + " " + y + " " + c);
			out.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			trash();
			active = false;
			viewListener.disconnected();
		}
	}

	@Override
	public void gameOver(GameOverType go) {
		// TODO Auto-generated method stub
		try {
			out.write("g " + go);
			out.flush();
		} catch (IOException e) {
			if (active) {
				trash();
				active = false;
				viewListener.disconnected();
			}
		}
	}

	public Socket getSocket() {
		return connection;
	}
	/**
	 * Reading thread of the socket
	 * @author James Masco
	 *
	 */
	private class ReaderThread extends Thread {
		ViewProxy parent;
		Socket sock;
		BufferedReader buf;

		/**
		 * Constructor for the reader thread
		 * 
		 * @param csp
		 *            Proxy for the thread to be reading for
		 */
		
		public ReaderThread(ViewProxy csp) {
			parent = csp;
			sock = parent.getSocket();
			try {
				buf = new BufferedReader(new InputStreamReader(
						sock.getInputStream()));
			} catch (IOException e) {
				// TODO Auto-generated catch block
				trash();
				active = false;
				viewListener.disconnected();
				;

			}

		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			while (true) {
				if (!active) {
					Thread.currentThread().interrupt();
					break;
				} else {
					try {
						String command = buf.readLine();
						if (command == null) {
							trash();
							active = false;
							viewListener.disconnected();
						}
						else {
							parent.processMsg(command);
						}
					} catch (IOException e) {
						// TODO Auto-generated catch block
						trash();
						active = false;
						if (viewListener != null)
						viewListener.disconnected();
					}
				}
			}
		}

	}

}
